home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / util / misc / VMM_src.lha / VMM / globals.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-16  |  10.1 KB  |  422 lines

  1. #include <exec/types.h>
  2. #include <exec/alerts.h>
  3.  
  4. static char rcsid [] = "$Id: globals.c,v 3.6 95/12/16 18:36:41 Martin_Apel Exp $";
  5.  
  6. #undef GLOBAL
  7. #define GLOBAL
  8.  
  9. #include "defs.h"
  10.  
  11. #define ERROR_STACK 2000L
  12.  
  13. PRIVATE UWORD ErrorLevel;
  14. PRIVATE char *ErrorString;
  15. PRIVATE struct Task *ErringTask;
  16. PRIVATE char ErrorBuffer [500];
  17. PRIVATE ULONG ErrorHandlerStack [ERROR_STACK/sizeof (ULONG)];
  18. PRIVATE struct Task ErrorHandlerTask;
  19.  
  20. PRIVATE struct EasyStruct ErrorReq =
  21.   {
  22.   sizeof (struct EasyStruct),
  23.   NULL,
  24.   PROGNAME,
  25.   ErrorBuffer,
  26.   NULL
  27.   };
  28.  
  29. PRIVATE APTR ErrorMsg [] = 
  30.   {
  31.   NULL,        /* SUCCESS */
  32.   NULL,        /* ERR_MSG_POSTED */
  33.   msgNotEnoughMem,
  34.   msgNoPagingFile,
  35.   msgNoSpace,
  36.   msgFailedIo,
  37.   msgFileIsDir,
  38.   msgInternal,
  39.   msgInhibitFailed,
  40.   msgWrongBlocksize,
  41.   msgNoDiskinfo,
  42.   msgNotValidated,
  43.   msgOutOfBounds,
  44.   msgNoFFS,
  45.   msgNoConfigFile,
  46.   msgCorruptCfgFile,
  47.   msgVolumeNotFound,
  48.   msgLowVersion,
  49.   msgNoDOS,
  50.   msgNoIntuition,
  51.   msgNoGfx,
  52.   msgNoUtility,
  53.   msgNoExpansion,
  54.   msgNoCommodities,
  55.   msgWrongCPU,
  56.   msgNoAddrSpace,
  57.   msgNoPrefs,
  58.   msgNoStatwindow,
  59.   msgNoRexx,
  60.   msgDynMapFailed
  61.   };
  62.  
  63.  
  64. /*********************************************************************/
  65.  
  66. PRIVATE void ErrorTask (void)
  67.  
  68. {
  69. PRINT_DEB ("ErrorTask alive", 0L);
  70.  
  71. sprintf (ErrorBuffer, GetVMMString (msgGenericError),
  72.          (ErrorLevel == ERR_NOERROR) ? GetVMMString (msgMessage) : GetVMMString (msgError),
  73.          ErringTask->tc_Node.ln_Name, ErrorString);
  74.  
  75. if (ErrorLevel == ERR_FATAL)
  76.   ErrorReq.es_GadgetFormat = GetVMMString (msgReboot);
  77. else
  78.   ErrorReq.es_GadgetFormat = GetVMMString (msgOK);
  79.  
  80. EasyRequestArgs (NULL, &ErrorReq, NULL, NULL);
  81.  
  82. if (ErrorLevel == ERR_FATAL)
  83.   {
  84.   PRINT_DEB ("Fatal error. Rebooting...", 0L);
  85.   ColdReboot ();
  86.   }
  87. else
  88.   PRINT_DEB ("Continuing after error", 0L);
  89. ENABLE_VM;          /* Corresponding DISABLE_VM has been done by ReportError */
  90. }
  91.  
  92. /*********************************************************************/
  93.  
  94. void ReportError (char *error_string, UWORD error_level)
  95.  
  96. {
  97. PRINT_DEB ("ReportError called", 0L);
  98.  
  99. DISABLE_VM;
  100. if (FindTask (ERR_NAME) != NULL)
  101.   {
  102.   PRINT_DEB ("Couldn't post error message. Error task already existed", 0L);
  103.   return;
  104.   }
  105.  
  106. ErrorHandlerTask.tc_Node.ln_Type = NT_TASK;
  107. ErrorHandlerTask.tc_Node.ln_Name = ERR_NAME;
  108. ErrorHandlerTask.tc_Node.ln_Pri = 10;
  109. ErrorHandlerTask.tc_SPReg = &(ErrorHandlerStack [ERROR_STACK/sizeof (ULONG) - 1]);
  110. ErrorHandlerTask.tc_SPLower = &(ErrorHandlerStack [0]);
  111. ErrorHandlerTask.tc_SPUpper = &(ErrorHandlerStack [ERROR_STACK/sizeof (ULONG) - 1]);
  112. NewList (&(ErrorHandlerTask.tc_MemEntry));
  113.  
  114. ErrorLevel = error_level;
  115. ErringTask = FindTask (NULL);
  116. ErrorString = error_string;
  117.  
  118. PRINT_DEB ("Creating error task", 0L);
  119. if (AddTask (&ErrorHandlerTask, ErrorTask, NULL) == NULL)
  120.   {
  121.   PRINT_DEB ("Error creating error task", 0L);
  122.   if (ErrorLevel == ERR_FATAL)
  123.     Alert (AT_DeadEnd | AG_IOError | AN_Unknown);
  124.   else
  125.     Alert (AT_Recovery | AG_IOError | AN_Unknown);
  126.   }
  127. PRINT_DEB ("Successfully created error task", 0L);
  128. }
  129.  
  130. /***********************************************************************/
  131.  
  132. void InitError (int num)
  133.  
  134. {
  135. if (num == ERR_MSG_POSTED)
  136.   return;
  137.  
  138. if (num > ERR_MAX_ERRNO)
  139.   {
  140.   PRINT_DEB ("InitError: Illegal error number %ld", (ULONG)num);
  141. #ifdef DEBUG
  142.   ColdReboot ();
  143. #endif
  144.   num = ERR_INTERNAL;
  145.   }
  146.  
  147. ReportError (GetVMMString (ErrorMsg [num]), ERR_CONTINUE);
  148. }
  149.  
  150. /***********************************************************************/
  151.  
  152. void RunTimeError (int num)
  153.  
  154. {
  155. InitError (num);
  156. }
  157.  
  158. /***********************************************************************/
  159.  
  160. void FatalError (int num)
  161.  
  162. {
  163. if (num > ERR_MAX_ERRNO)
  164.   {
  165.   PRINT_DEB ("FatalError: Illegal error number %ld", (ULONG)num);
  166. #ifdef DEBUG
  167.   ColdReboot ();
  168. #endif
  169.   num = ERR_INTERNAL;
  170.   }
  171.  
  172. ReportError (ErrorMsg [num], ERR_FATAL);
  173. Wait (0L);          /* Wait forever */
  174. }
  175.  
  176. /***********************************************************************/
  177.  
  178. void *AllocAligned (ULONG size, ULONG flags, ULONG alignment, ULONG priority)
  179.  
  180. /* Allocates "size" bytes aligned at an "alignment" boundary.
  181.  * "alignment" must be a power of two and larger than the minimum
  182.  * memory size (currently 8 bytes).
  183.  * Supported flags are MEMF_PUBLIC, MEMF_CHIP, MEMF_FAST, MEMF_REVERSE.
  184.  * Priority is a hint on how much time should be spent in AllocAligned.
  185.  * 0 is the highest priority, it means: Do whatever you can to make
  186.  * memory available. For lower values, 'priority' gives the number of
  187.  * bytes which must be available in a memory region to make AllocAligned
  188.  * step into it and search.
  189.  */
  190. {
  191. struct MemHeader *mh;
  192. struct MemChunk **cur_mc,
  193.                 **chosen_mc;
  194.  
  195. #ifdef DEBUG
  196. if (size % alignment != 0)
  197.   {
  198.   ReportError ("Internal error in AllocAligned:\n"
  199.                "size not multiple of alignment", ERR_CONTINUE);
  200.   return (NULL);
  201.   }
  202. #endif
  203.  
  204. Forbid ();
  205. CHECK_CONSISTENCY;
  206. chosen_mc = NULL;
  207. for (mh = (struct MemHeader*)SysBase->MemList.lh_Head;
  208.      mh->mh_Node.ln_Succ != NULL;
  209.      mh = (struct MemHeader*)mh->mh_Node.ln_Succ)
  210.   {
  211.   /* Check flags */
  212.   if (((mh->mh_Attributes & flags) == (flags & (MEMF_CHIP | MEMF_FAST | MEMF_PUBLIC)))
  213.       && (mh->mh_Free > priority))
  214.     {
  215.     if (flags & MEMF_REVERSE)
  216.       {
  217.       /* Use last fitting chunk */
  218.       for (cur_mc = &(mh->mh_First); *cur_mc != NULL;
  219.            cur_mc = &((*cur_mc)->mc_Next))
  220.         {
  221.         if (((*cur_mc)->mc_Bytes >= size) &&
  222.             (ALIGN_UP ((ULONG)*cur_mc, alignment) + size <=
  223.                                    (ULONG)*cur_mc + (*cur_mc)->mc_Bytes))
  224.           chosen_mc = cur_mc;
  225.         }
  226.       }
  227.     else
  228.       {
  229.       /* Use first fitting chunk */
  230.       for (cur_mc = &(mh->mh_First); *cur_mc != NULL;
  231.            cur_mc = &((*cur_mc)->mc_Next))
  232.         {
  233.         if (((*cur_mc)->mc_Bytes >= size) &&
  234.             (ALIGN_UP ((ULONG)*cur_mc, alignment) + size <=
  235.                                    (ULONG)*cur_mc + (*cur_mc)->mc_Bytes))
  236.  
  237.           {
  238.           chosen_mc = cur_mc;
  239.           break;
  240.           }
  241.         }
  242.       }
  243.     if (chosen_mc != NULL)
  244.       break;
  245.     }
  246.   }
  247.  
  248. if (chosen_mc == NULL)
  249.   {
  250.   void *tmp_buffer = NULL;
  251.  
  252.   CHECK_CONSISTENCY;
  253.   if (priority == 0L)
  254.     {
  255.     PRINT_DEB ("AllocAligned: Executing avail flush", 0L);
  256.     if (FindTask (NULL) == PageHandlerTask)
  257.       {
  258.       PRINT_DEB ("Pagehandler is executing avail flush !!!", 0L);
  259.       tmp_buffer = DoOrigAllocMem (2 * size, flags);
  260.       }
  261.     else
  262.       tmp_buffer = AllocMem (2 * size, flags);
  263.  
  264.     if (tmp_buffer != NULL)
  265.       {
  266.       FreeMem (tmp_buffer, 2 * size);
  267.       tmp_buffer = AllocAligned (size, flags, alignment, 1L);
  268.       }
  269.     }
  270.   Permit ();
  271.   return (tmp_buffer);
  272.   }
  273. else
  274.   {
  275.   ULONG start_alloc;
  276.   struct MemChunk *new_chunk,
  277.                   *tmp_chunk;
  278.   ULONG chunk_size;
  279.  
  280.   tmp_chunk = *chosen_mc;
  281.   /* Found a fitting chunk. Do the allocation */
  282.   if (flags & MEMF_REVERSE)
  283.     {
  284.     start_alloc = ALIGN_DOWN ((ULONG)tmp_chunk + tmp_chunk->mc_Bytes, alignment)
  285.                   - size;
  286.     }
  287.   else
  288.     start_alloc = ALIGN_UP ((ULONG)tmp_chunk, alignment);
  289.  
  290.   chunk_size = tmp_chunk->mc_Bytes - size;     /* size of remaining mem */
  291.  
  292.   if ((ULONG)tmp_chunk < start_alloc)
  293.     {
  294.     /* Make this chunk smaller */
  295.     tmp_chunk->mc_Bytes = start_alloc - (ULONG)tmp_chunk;
  296.     chunk_size -= tmp_chunk->mc_Bytes;
  297.     chosen_mc = &(tmp_chunk->mc_Next);
  298.     }
  299.  
  300.   if (chunk_size > 0)
  301.     {
  302.     new_chunk = (struct MemChunk*)(start_alloc + size);
  303.     new_chunk->mc_Next = tmp_chunk->mc_Next;
  304.     new_chunk->mc_Bytes = chunk_size;
  305.     *chosen_mc = new_chunk;
  306.     }
  307.   else
  308.     *chosen_mc = tmp_chunk->mc_Next;
  309.  
  310.   mh->mh_Free -= size;
  311.  
  312.   CHECK_CONSISTENCY;
  313.   Permit ();
  314.   return ((void*)start_alloc);
  315.   }
  316. }
  317.  
  318. /***********************************************************************/
  319.  
  320. #define isspace(c) (((c)==' ') || ((c) == '\t') || ((c) == '\n'))
  321.  
  322. void GetNthString (char *from, char *to, int n)
  323.  
  324. {
  325. /* Extracts the nth string in the line "from" and copies it to "to".
  326.  * If the nth string does not exist 'to' is set to an empty string.
  327.  */
  328. char *tmp1, *tmp2;
  329.  
  330. tmp1 = from;
  331. tmp2 = to;
  332. while (*tmp1 != 0 && isspace (*tmp1)) tmp1++;    /* skip leading whitespace */
  333.  
  334. while (--n > 0)
  335.   {
  336.   while (*tmp1 != 0 && !isspace (*tmp1)) tmp1++; /* skip word */
  337.   while (*tmp1 != 0 &&  isspace (*tmp1)) tmp1++; /* skip blanks */
  338.   }
  339.  
  340. while (*tmp1 != 0 && !isspace(*tmp1)) *tmp2++ = *tmp1++;
  341. *tmp2 = 0;
  342. }
  343.  
  344. /***********************************************************************/
  345.  
  346. void StrToHex (char *string, ULONG *val)
  347.  
  348. {
  349. char *tmp;
  350.  
  351. tmp = string;
  352. *val = 0;
  353. while (*tmp != 0 && isspace(*tmp))
  354.   tmp++;
  355.  
  356. while (*tmp != 0 && !isspace (*tmp))
  357.   {
  358.   *val = (*val << 4);
  359.  
  360.   if (*tmp >= '0' && *tmp <= '9')
  361.     *val += *tmp - '0';
  362.   else if (*tmp >= 'a' && *tmp <= 'f')
  363.     *val += *tmp - 'a' + 10;
  364.   else if (*tmp >= 'A' && *tmp <= 'F')
  365.     *val += *tmp - 'F' + 10;
  366.   else
  367.     {
  368.     return;
  369.     }
  370.  
  371.   tmp++; 
  372.  }
  373. }
  374.  
  375. /***********************************************************************/
  376.  
  377. void EmptyPageCollector (void)
  378.  
  379. /* Routine for a task that is created after a specified number of FreeMems on
  380.  * virtual memory. It traverses the memory list for virtual memory and
  381.  * frees the pages and frames of unused pages.
  382.  */
  383. {
  384. struct VMMsg *FreeMsg;
  385. UWORD ReplySignal;
  386. struct MemChunk *chunk;
  387.  
  388. PRINT_DEB ("EmptyPageCollector running", 0L);
  389.  
  390. if ((FreeMsg = AllocMem (sizeof (struct VMMsg), MEMF_PUBLIC)) == NULL)
  391.   return;
  392.  
  393. ReplySignal = AllocSignal (-1L);        /* Guaranteed to succeed */
  394. FreeMsg->VMSender = FindTask (NULL);
  395. FreeMsg->VMCommand = VMCMD_FreePages;
  396. FreeMsg->ReplySignal = ReplySignal;
  397.  
  398. PRINT_DEB ("Obtaining VM sema", 0L);
  399. OBTAIN_VM_SEMA;
  400. PRINT_DEB ("VM sema obtained", 0L);
  401.  
  402. for (chunk = VirtMem->mh_First; chunk != NULL; chunk = chunk->mc_Next)
  403.   {
  404.   if ((ULONG)chunk + chunk->mc_Bytes > ALIGN_UP ((ULONG)(chunk + 1) + PAGESIZE, PAGESIZE))
  405.     {
  406.     /* There is at least one page contained in this are */
  407.     FreeMsg->FreeAddress = (ULONG)(chunk + 1);
  408.     FreeMsg->FreeSize = chunk->mc_Bytes - sizeof (struct MemChunk);
  409.     PutMsg (PageHandlerPort, (struct Message*) FreeMsg);
  410.     Wait (1L << ReplySignal);
  411.     }
  412.   }
  413.  
  414. PRINT_DEB ("Releasing VM sema", 0L);
  415. RELEASE_VM_SEMA;
  416. FreeMem (FreeMsg, sizeof (struct VMMsg));
  417. FreeSignal ((LONG)ReplySignal);
  418.  
  419. VMFreeCounter = COLLECT_INTERVAL;
  420. PRINT_DEB ("EmptyPageCollector terminating", 0L);
  421. }
  422.